<?php

namespace app;

use Throwable;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\Exception\ExceptionHandler;

class Handler extends ExceptionHandler
{
    public function render(Request $request, Throwable $exception): Response
    {
        $result = [
            "code" => $exception->getCode() ?: 500,
            "message" => $exception->getMessage(),
            "file" => $exception->getFile(),
            "line" => $exception->getLine(),
            "backtrace" => $exception->getTraceAsString(),
            "content" => $this->getFileContent($exception->getFile(), $exception->getLine())
        ];
        $type = $this->getResponseType();
        if ('html' == strtolower($type)) {
            static $handler;
            if (null === $handler) {
                $handler = config('view.handler');
            }
            $body = $handler::render(BASE_PATH . '/public/error/500.html', []);
            if ($this->debug) {
                $body = $handler::render(BASE_PATH . '/public/handler.html', $result);
            }
            return new Response(
                $result['code'],
                ['Content-Type' => 'text/html; charset=utf-8'],
                $body
            );
        } else {
            if (!$this->debug) {
                $result = [
                    "code" => $exception->getCode() ?: 500,
                    "message" => $exception->getMessage(),
                ];
            }
            return new Response(
                $result['code'],
                ['Content-Type' => 'application/json'],
                json_encode($result, JSON_UNESCAPED_UNICODE)
            );
        }
    }

    /**
     * 获取当前的response 输出类型
     *
     * @return string
     */
    private function getResponseType(): string
    {
        if (request() != null) {
            return  request()->acceptJson() || request()->isAjax() ? 'json' : 'html';
        } else {
            return 'json';
        }
    }

    /**
     * 获取报错文件内容 function
     *
     * @param string $file
     * @param integer $line
     * @return array
     */
    private function getFileContent(string $file, int $line): array
    {
        // 打开文件并读取内容  
        $content = file($file);
        $str = "";
        $conLine = 0;
        if ($content) {
            $lines = array_slice($content, ($line - 10), ($line + 20) - ($line - 10) + 1);
            // 输出获取到的内容  
            foreach ($lines as $k => $v) {
                // 当是当前行等于报错行的时候，输出红色字体
                if ($v == $content[$line - 1]) {
                    $conLine = $k;
                }
                $str .= $v;
            }
            return ["msg" => $str, "line" => $conLine];
        } else {
            return ['msg' => '无法读取文件内容。', 'line' => $conLine];
        }
    }
}
